/*
 * addon_entry.cpp
 *
 *  Created on: 2010-1-7
 *      Author: gavinkwoe
 */

#include "addon_features.h"

#if (__ADDON_TARGET__ == __TARGET_SYMBIAN)

#include "addon_std.h"
#include "addon_mem.h"
#include "addon_objbase.h"
#include "addon_timer.h"

#if defined(__ADDON_USE_CX_TIMER__)
#include "cx_timer.h"
#else	// #if defined(__ADDON_USE_CX_TIMER__)
#include <e32base.h>
#endif	// #if defined(__ADDON_USE_CX_TIMER__)

/*************************************************************************
* GUID
*************************************************************************/

ADDON_DEFINED_GUID( IAddonTimer, 1, "E18DC933-DF0D-4c32-95D9-BF748EBAC682" )

/*************************************************************************
* PROTOTYPE
*************************************************************************/

struct __struct_addon_Timer_data;
typedef struct __struct_addon_Timer_data	addon_Timer_data_t;
typedef struct __struct_addon_Timer_data *	addon_Timer_data_ptr_t;

/*************************************************************************
* STRUCTURE
*************************************************************************/

struct __struct_addon_Timer_data
{
	unsigned long			ref_cnt;	// reference count
	addon_timeout_fptr_t	cb_hdlr;
	unsigned long			has_ud;	
	void *					user_data;
#if defined(__ADDON_USE_CX_TIMER__)
	QINT					timer_id;
#else	// #if defined(__ADDON_USE_CX_TIMER__)
	CPeriodic *				timer;
#endif	// #if defined(__ADDON_USE_CX_TIMER__)
};

/*************************************************************************
* LOCAL FUNCTIONS
*************************************************************************/

unsigned long	__CTimer_Construct( ADDON_REF(IObject) thiz, void * usr_data );
unsigned long	__CTimer_Destruct( ADDON_REF(IObject) thiz );
unsigned long	__CTimer_AddRef( ADDON_REF(IObject) thiz );
unsigned long	__CTimer_Release( ADDON_REF(IObject) thiz );

unsigned long	__CTimer_GetUserData( ADDON_REF(IObject) thiz, void ** pusr_data );
unsigned long	__CTimer_SetUserData( ADDON_REF(IObject) thiz, void * usr_data );
unsigned long	__CTimer_SetCallback( ADDON_REF(IObject) thiz, addon_timeout_fptr_t cb_hdlr );
unsigned long	__CTimer_Start( ADDON_REF(IObject) thiz, unsigned long delay_ms );
unsigned long	__CTimer_Stop( ADDON_REF(IObject) thiz );

#if defined(__ADDON_USE_CX_TIMER__)
static QINT				__timeout_callback( QINT nTimerId, QVOID * pObject );
#else	// #if defined(__ADDON_USE_CX_TIMER__)
static TInt				__timeout_callback( TAny * aPtr );
#endif	// #if defined(__ADDON_USE_CX_TIMER__)

// const void * const __coclass_vtbl[] =
// {
// 	// IObject
// 	(void *)__CTimer_Construct,
// 		(void *)__CTimer_Destruct,
// 		(void *)__CTimer_AddRef,
// 		(void *)__CTimer_Release,
// 		
// 		// IAddonDLL
// 		(void *)__CTimer_GetUserData,
// 		(void *)__CTimer_SetUserData,
// 		(void *)__CTimer_SetCallback,
// 		(void *)__CTimer_Start,
// 		(void *)__CTimer_Stop
// };
// 
// const addon_coclass_desc_t __coclass_desc =
// {
// 	(unsigned char *)__coclass_vtbl,
// 		(unsigned long)sizeof( addon_Timer_data_t )
// };

/*************************************************************************
* IMPLEMENTATION
*************************************************************************/

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_Construct( ADDON_REF(IObject) thiz, void * usr_data )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	ADDON_UNUSED( usr_data );
	
	if ( NULL == obj_data )
		return ADDON_FAILED;

	obj_data->ref_cnt	= 1;
	obj_data->cb_hdlr	= NULL;
	obj_data->has_ud	= ADDON_FALSE;
	obj_data->user_data	= NULL;

#if defined(__ADDON_USE_CX_TIMER__)
#else	// #if defined(__ADDON_USE_CX_TIMER__)
	obj_data->timer		= NULL;
#endif	// #if defined(__ADDON_USE_CX_TIMER__)
	
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_Destruct( ADDON_REF(IObject) thiz )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;

	__CTimer_Stop( thiz );
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_AddRef( ADDON_REF(IObject) thiz )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;
	
	obj_data->ref_cnt++;
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_Release( ADDON_REF(IObject) thiz )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;
	
	obj_data->ref_cnt -= 1;

	if ( 0 == obj_data->ref_cnt )
	{
		addon_obj_delete( (void *)thiz );
	}
	
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_GetUserData( ADDON_REF(IObject) thiz, void ** pusr_data )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data || NULL == pusr_data )
		return ADDON_FAILED;
	
	if ( ADDON_FALSE == obj_data->has_ud )
		return ADDON_FAILED;
	
	*pusr_data = obj_data->user_data;
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_SetUserData( ADDON_REF(IObject) thiz, void * usr_data )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;
	
	obj_data->has_ud	= ADDON_TRUE;
	obj_data->user_data	= usr_data;
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_SetCallback( ADDON_REF(IObject) thiz, addon_timeout_fptr_t hdlr )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;
	
	obj_data->cb_hdlr = hdlr;
	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
#if defined(__ADDON_USE_CX_TIMER__)
static QINT __timeout_callback( QINT nTimerId, QVOID * pObject )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( pObject );
	
	if ( NULL == obj_data->timer_id )
		return 1;
	
	if ( NULL != obj_data->cb_hdlr )
	{
		ADDON_INVOKE( obj_data->cb_hdlr, ( (ADDON_REF(IObject))pObject ) );
	}

	return 1;
}
#else	// #if defined(__ADDON_USE_CX_TIMER__)
static TInt __timeout_callback( TAny * aPtr )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( aPtr );
	
	if ( NULL == obj_data->timer )
		return ETrue;
	
	if ( NULL != obj_data->cb_hdlr )
	{
		ADDON_INVOKE( obj_data->cb_hdlr, ( (ADDON_REF(IObject))aPtr ) );
	}

	return ETrue;
}
#endif	// #if defined(__ADDON_USE_CX_TIMER__)

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_Start( ADDON_REF(IObject) thiz, unsigned long delay_ms )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;

	__CTimer_Stop( thiz );

#if defined(__ADDON_USE_CX_TIMER__)
	obj_data->timer_id = cx_timer_start( (QDWORD)delay_ms, (cxTimerCallBack)__timeout_callback, (QVOID *)thiz );
	if ( 0 == obj_data->timer_id )
		return ADDON_FAILED;
#else	// #if defined(__ADDON_USE_CX_TIMER__)	
	obj_data->timer = CPeriodic::NewL( CActive::EPriorityStandard );
	if ( NULL == obj_data->timer )
		return ADDON_FAILED;

	obj_data->timer->Start( delay_ms, delay_ms, TCallBack(__timeout_callback, thiz));
#endif	// #if defined(__ADDON_USE_CX_TIMER__)

	return ADDON_OK;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __CTimer_Stop( ADDON_REF(IObject) thiz )
{
	addon_Timer_data_ptr_t obj_data = (addon_Timer_data_ptr_t)ADDON_GET_DATA( thiz );

	if ( NULL == obj_data )
		return ADDON_FAILED;

#if defined(__ADDON_USE_CX_TIMER__)
	if ( 0 != obj_data->timer_id )
	{
		cx_timer_stop( obj_data->timer_id );
		obj_data->timer_id = 0;	
	}
#else	// #if defined(__ADDON_USE_CX_TIMER__)
	if ( NULL != obj_data->timer )
	{
		if ( obj_data->timer->IsActive() )
		{
			obj_data->timer->Cancel();
		}

		delete obj_data->timer;
		obj_data->timer = NULL;
	}
#endif	// #if defined(__ADDON_USE_CX_TIMER__)
	
	return ADDON_OK;	
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
ADDON_EXPORT ADDON_REF(IObject) addon_create_timer( void * reserved )
{
	//static const 
		void * __coclass_vtbl[9];// =
	int i=0;//{
		// IObject
__coclass_vtbl[i++] = 	(void *)__CTimer_Construct;
__coclass_vtbl[i++] = 	(void *)__CTimer_Destruct;
__coclass_vtbl[i++] = 	(void *)__CTimer_AddRef;
__coclass_vtbl[i++] = 	(void *)__CTimer_Release;

		// IAddonDLL
__coclass_vtbl[i++] = 	(void *)__CTimer_GetUserData;
__coclass_vtbl[i++] = 	(void *)__CTimer_SetUserData;
__coclass_vtbl[i++] = 	(void *)__CTimer_SetCallback;
__coclass_vtbl[i++] = 	(void *)__CTimer_Start;
__coclass_vtbl[i++] = 	(void *)__CTimer_Stop;
//	};
	
// 	static const addon_coclass_desc_t __coclass_desc =
// 	{
// 		(unsigned char *)__coclass_vtbl,
// 		(unsigned long)sizeof( addon_Timer_data_t )
// 	};
		addon_coclass_desc_t __coclass_desc;
		
		__coclass_desc.vtbl_size	= (unsigned long)sizeof(__coclass_vtbl);
		__coclass_desc.vtbl_funcs	= (unsigned char *)__coclass_vtbl;
		__coclass_desc.priv_size	= (unsigned long)sizeof(addon_Timer_data_t);
		


	return ( ADDON_REF(IObject) )addon_obj_new( (addon_coclass_desc_ptr_t)&__coclass_desc, reserved );
}

#else	// #if (__ADDON_TARGET__ == __TARGET_SYMBIAN)

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
ADDON_EXPORT ADDON_REF(IObject) addon_create_timer( void * reserved )
{
	ADDON_UNUSED( reserved );
	return NULL;
}

#endif	// #if (__ADDON_TARGET__ == __TARGET_SYMBIAN)
